package com.webchat.connect.messagequeue.consumer.service;


import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Sets;
import com.webchat.common.constants.ConnectConstants;
import com.webchat.common.enums.AccountRelationTypeEnum;
import com.webchat.common.enums.RoleCodeEnum;
import com.webchat.common.enums.messagequeue.MessageQueueEnum;
import com.webchat.common.service.messagequeue.producer.MessageQueueProducer;
import com.webchat.common.util.JsonUtil;
import com.webchat.connect.service.AccountService;
import com.webchat.connect.websocket.handler.ChatWebSocketEndPointServletHandler;
import com.webchat.domain.vo.request.mess.ChatMessageRequestVO;
import com.webchat.domain.vo.request.mess.MessageBaseVO;
import com.webchat.domain.vo.response.RedPacketBaseVO;
import com.webchat.domain.vo.response.UserBaseResponseInfoVO;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@Service
public class RedPacketNotifyConsumeService {


    @Autowired
    private AccountService accountService;

    @Autowired
    private MessageQueueProducer<ChatMessageRequestVO, Long> messageQueueProducer;


    /**
     * 红包通知消费（来自广播）
     *
     * @param messageJson
     */
    public void consume(String messageJson) {

        if (StringUtils.isBlank(messageJson)) {
            return;
        }
        MessageBaseVO<RedPacketBaseVO> message =
                JsonUtil.fromJson(messageJson, new TypeReference<MessageBaseVO<RedPacketBaseVO>>() { });

        // 判断红包接受账号是群聊还是机器人
        String senderId = message.getSenderId();
        String receiverId = message.getReceiverId();


        Map<String, UserBaseResponseInfoVO> users = accountService.batchGet(Sets.newHashSet(receiverId, senderId));

        UserBaseResponseInfoVO receiver = users.get(receiverId);
        UserBaseResponseInfoVO sender = users.get(senderId);

        Set<String> realReceiverIds = new HashSet<>();
        realReceiverIds.add(senderId);
        if (RoleCodeEnum.isUserRole(receiver.getRoleCode())) {
            // 红包接受人是普通用户
            realReceiverIds.add(receiverId);
        } else if (RoleCodeEnum.GROUP.getCode().equals(receiver.getRoleCode())) {
            // 红包接受人是群组
            Set<String> groupUserIds = accountService.getAllSubscriberByAccount(receiverId, AccountRelationTypeEnum.USER_GROUP);
            realReceiverIds.addAll(groupUserIds);
            /**
             * 消息代理人，由群聊代理实际红包发送人
             */
            // 群聊代理
            message.setSenderId(receiverId);
            message.setSender(receiver);
            // 实际红包发送人
            message.setProxySender(sender);
            message.setProxySenderId(senderId);
        } else {
            return;
        }
        /**
         * 通知接受人“红包来了”，并且前端渲染红包卡片效果
         */
        this.doNotifyByWebSocket(realReceiverIds, message);

        /**
         * 《离线场景》持久化消息队列，保存离线消息，同时会将数据同步到ES用于后续的RAG问答和消息搜索
         *
         *  Consumer在UGC服务：
         *  com.webchat.ugc.messaegqueue.consumer.redis.PersistentMessageRedisMQConsumer
         *  com.webchat.ugc.messaegqueue.consumer.rocketmq.PersistentMessageRocketMQConsumer
         */
        ChatMessageRequestVO chatMessageRequestVO = new ChatMessageRequestVO();
        chatMessageRequestVO.setSenderId(senderId);
        chatMessageRequestVO.setReceiverId(receiverId);
        chatMessageRequestVO.setType(message.getType());
        chatMessageRequestVO.setMessage(String.valueOf(message.getMessageExt().getId()));
        messageQueueProducer.send(MessageQueueEnum.QUEUE_PERSISTENT_MESSAGE, chatMessageRequestVO);
    }

    private void doNotifyByWebSocket(Set<String> receiverUserIds, MessageBaseVO<RedPacketBaseVO> message) {

        String messageJson = JsonUtil.toJsonString(message);
        // 处理所有客户端消息推送，比如MAC、WIN、PC-WEB……
        Set<String> bizCodes = ConnectConstants.ConnectBiz.getBizCode(ConnectConstants.BizEnum.CHAT);
        for (String bizCode : bizCodes) {
            // 批量获取接受人在当前节点的ws链接对象
            Map<String, WebSocketSession> wsSessionMap = ChatWebSocketEndPointServletHandler.getSessions(bizCode, receiverUserIds);
            if (MapUtils.isEmpty(wsSessionMap)) {
                continue;
            }
            for (String receiverId : receiverUserIds) {
                WebSocketSession session = wsSessionMap.get(receiverId);
                if (session == null || !session.isOpen()) {
                    continue;
                }
                try {
                    session.sendMessage(new TextMessage(messageJson));
                } catch (IOException e) {
                    // TODO
                    e.printStackTrace();
                }
            }
        }

    }
}
